/**
 * @file tcp_server_app_misc.c
 * @brief Helper functions for TcpApp/TCP server
 * @Author: aple
 * @Date: 2025-9-27 9:20:10
 * @LastEditors: aple
 * @LastEditTime: 2025-9-27 18:37:50
 * @Verision: 1.0.0.0
 **/

// Switch to the appropriate trace level
#define TRACE_LEVEL TCP_APP_TRACE_LEVEL

// Dependencies
#include "server/tcp_server_app.h"
#include "server/tcp_server_app_adu.h"
#include "server/tcp_server_app_transport.h"
#include "server/tcp_server_app_misc.h"
#include "debug.h"

/**
 * @brief Handle periodic operations
 * @param[in] context Pointer to the TcpApp/TCP server context
 **/

void TcpAppServerTick(TcpAppServerContext *context)
{
   uint_t i;
   systime_t time;
   systime_t timeout;
   TcpAppClientConnection *connection;

   // Get current time
   time = osGetSystemTime();

   // Loop through the connection table
   for (i = 0; i < TCP_APP_SERVER_MAX_CONNECTIONS; i++)
   {
      // Point to the current entry
      connection = &context->connection[i];

      // Check the state of the current connection
      if (connection->state != TCP_APP_CONNECTION_STATE_CLOSED)
      {
         // Retrieve idle connection timeout
         timeout = context->settings.timeout;

         // A value of zero means no timeout
         if (timeout != 0)
         {
            // Disconnect inactive client after idle timeout
            if (timeCompare(time, connection->timestamp + timeout) >= 0)
            {
               // Debug message
               TRACE_INFO("TcpApp server: Closing inactive connection...\r\n");
               // Close the TcpApp/TCP connection
               TcpAppServerCloseConnection(connection);
            }
         }
      }
   }

   // Any registered callback?
   if (context->settings.tickCallback != NULL)
   {
      // Invoke user callback function
      context->settings.tickCallback(context);
   }
}

/**
 * @brief Register connection events
 * @param[in] connection Pointer to the client connection
 * @param[in] eventDesc Socket events to be registered
 **/

void TcpAppServerRegisterConnectionEvents(TcpAppClientConnection *connection,
                                          SocketEventDesc *eventDesc)
{
   // Check the state of the connection
   if (connection->state == TCP_APP_CONNECTION_STATE_RECEIVE)
   {
      // Wait for data to be available for reading
      eventDesc->socket = connection->socket;
      eventDesc->eventMask = SOCKET_EVENT_RX_READY;
   }
   else if (connection->state == TCP_APP_CONNECTION_STATE_SEND)
   {
      // Wait until there is more room in the send buffer
      eventDesc->socket = connection->socket;
      eventDesc->eventMask = SOCKET_EVENT_TX_READY;
   }
   else if (connection->state == TCP_APP_CONNECTION_STATE_SHUTDOWN_TX)
   {
      // Wait for the FIN to be acknowledged
      eventDesc->socket = connection->socket;
      eventDesc->eventMask = SOCKET_EVENT_TX_SHUTDOWN;
   }
   else if (connection->state == TCP_APP_CONNECTION_STATE_SHUTDOWN_RX)
   {
      // Wait for a FIN to be received
      eventDesc->socket = connection->socket;
      eventDesc->eventMask = SOCKET_EVENT_RX_SHUTDOWN;
   }
   else
   {
      // Just for sanity
   }
}

/**
 * @brief Connection event handler
 * @param[in] connection Pointer to the client connection
 **/

void TcpAppServerProcessConnectionEvents(TcpAppClientConnection *connection)
{
   error_t error;
   size_t n;
   TcpAppServerContext *context;

   // Initialize status code
   error = NO_ERROR;

   // Point to the TcpApp/TCP server context
   context = connection->context;
   // Update time stamp
   connection->timestamp = osGetSystemTime();

   // Check the state of the connection
   if (connection->state == TCP_APP_CONNECTION_STATE_RECEIVE)
   {
      // Receive TcpApp request

         // Receive more data
         error = TcpAppServerReceiveData(connection,
                                         connection->requestAdu + connection->requestAduPos,
                                         sizeof(connection->requestAdu) - connection->requestAduPos, &n, 0);

         // 此处根据应用修改
         if(connection->requestAduPos == 0)
         {
         }
         
         #if 0
         // Check status code
         if (error == NO_ERROR)
         {
            // Advance data pointer
            connection->requestAduPos += n;

            // TcpApp request successfully received?
            if (connection->requestAduPos >= connection->requestAduLen)
            {
               // Total number of messages received
               context->rxMessageCount++;
               // Process TcpApp request
               error = TcpAppServerProcessRequest(connection);
            }
         }
         #else
         // 此处根据应用修改
		 connection->requestAduPos += n;
		 connection->requestAduLen = n;
         // Total number of messages received
         context->rxMessageCount++;
         // Process TcpApp request
         error = TcpAppServerProcessRequest(connection);
         #endif 
   }
   else if (connection->state == TCP_APP_CONNECTION_STATE_SEND)
   {
      // Send TcpApp response
      if (connection->responseAduPos < connection->responseAduLen)
      {
         // Send more data
         error = TcpAppServerSendData(connection,
                                      connection->responseAdu + connection->responseAduPos,
                                      connection->responseAduLen - connection->responseAduPos,
                                      &n, SOCKET_FLAG_NO_DELAY);

         // Check status code
         if (error == NO_ERROR || error == ERROR_TIMEOUT)
         {
            // Advance data pointer
            connection->responseAduPos += n;

            // TcpApp response successfully sent?
            if (connection->responseAduPos >= connection->responseAduLen)
            {
               // Total number of messages sent
               context->txMessageCount++;
               // Flush receive buffer
               connection->requestAduLen = 0;
               connection->requestAduPos = 0;
               // Wait for the next TcpApp request
               connection->state = TCP_APP_CONNECTION_STATE_RECEIVE;
            }
         }
      }
      else
      {
           // Flush receive buffer
           connection->requestAduLen = 0;
           connection->requestAduPos = 0;
           // Wait for the next TcpApp request
           connection->state = TCP_APP_CONNECTION_STATE_RECEIVE;
      }
   }
   else if (connection->state == TCP_APP_CONNECTION_STATE_SHUTDOWN_TX)
   {
      // Graceful connection shutdown
      error = TcpAppServerShutdownConnection(connection);
   }
   else if (connection->state == TCP_APP_CONNECTION_STATE_SHUTDOWN_RX)
   {
      // Close the TcpApp/TCP connection
      TcpAppServerCloseConnection(connection);
   }
   else
   {
      // Invalid state
      error = ERROR_WRONG_STATE;
   }

   // Any communication error?
   if (error != NO_ERROR && error != ERROR_TIMEOUT)
   {
      // Total number of communication errors
      context->commErrorCount++;

      // Close the TcpApp/TCP connection
      TcpAppServerCloseConnection(connection);
   }
}

/**
 * @brief Lock TcpApp table
 * @param[in] connection Pointer to the client connection
 **/

void TcpAppServerLock(TcpAppClientConnection *connection)
{
   TcpAppServerContext *context;

   // Point to the TcpApp/TCP server context
   context = connection->context;

   // Any registered callback?
   if (context->settings.lockCallback != NULL)
   {
      // Invoke user callback function
      context->settings.lockCallback(connection);
   }
}

/**
 * @brief Unlock TcpApp table
 * @param[in] connection Pointer to the client connection
 **/

void TcpAppServerUnlock(TcpAppClientConnection *connection)
{
   TcpAppServerContext *context;

   // Point to the TcpApp/TCP server context
   context = connection->context;

   // Any registered callback?
   if (context->settings.unlockCallback != NULL)
   {
      // Invoke user callback function
      context->settings.unlockCallback(connection);
   }
}
